<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pong Game</title>
    <style>
        * {
            touch-action: pan-y;
        }

        html,
        body {
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            margin: 0;
            padding: 0;
        }

        #root {
            display: flex;
            flex: 1 1 auto;
            color: white;
            background-color: black;
        }

        #menu {
            position: fixed;
            text-align: center;
            width: 100%;
            user-select: none;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        #play_ground {
            display: flex;
            flex: 1 1 auto;
            justify-content: space-between;
        }

        #player_a,
        #player_b {
            height: 100px;
            width: 10px;
            position: relative;
            background-color: white;
            transition: 0.1s linear;
            transition-property: top;
            will-change: top;
        }

        #ball {
            width: 10px;
            height: 10px;
            position: fixed;
            border-radius: 10px;
            background-color: white;
            transition-property: top, left;
            will-change: top, left;
        }

        #middle_line {
            border: 1px solid white;
            border-style: dashed;
        }
    </style>
</head>

<body>
    <div id="root">
        <div id="menu">
            <button id="menu_btn_stop"></button>
            <h1 id="menu_title"></h1>
        </div>
        <div id="play_ground">
            <div id="player_a"></div>
            <div id="ball"></div>
            <div id="middle_line"></div>
            <div id="player_b"></div>
        </div>
    </div>
    <p>Pong Game wirte by <a href="https://kingfish404.cn" target="_blank">Kingfish404</a></p>
    <script>
        var global = {
            width: document.getElementById('play_ground').clientWidth,
            height: document.getElementById('play_ground').clientHeight,
            half_width: document.getElementById('play_ground').clientWidth / 2,
            half_height: document.getElementById('play_ground').clientHeight / 2,
            game: {
                main: null,
                is_start: false,
                update: function () {
                    // ball chack
                    if (this.ball.data.y < 0 || this.ball.data.y > global.height) {
                        // hit up or down
                        this.ball.data.angle = 180 - this.ball.data.angle;
                    } else if (this.ball.data.x < 0) {
                        // console.log(this.ball.data.y, this.player_a.data.y, this.player_a.height / 2, this.ball.height)
                        setTimeout(() => {
                            if (this.ball.data.y > (this.player_a.data.y + this.player_a.height / 2 + this.ball.height) ||
                                this.ball.data.y < (this.player_a.data.y - this.player_a.height / 2 - this.ball.height)) {
                                gameOver();
                            }
                        }, 25);
                        var between = this.ball.data.y - this.player_a.data.y;
                        between = Math.min(between, 20);
                        between = Math.max(between, -20);
                        this.ball.data.angle = 360 - this.ball.data.angle - between + Math.random() * 10 - 5;
                        this.ball.data._speed *= 1.1;
                    } else if (this.ball.data.x > global.width) {
                        if (this.ball.data.y > (this.player_b.data.y + this.player_b.height / 2 + this.ball.height) ||
                            this.ball.data.y < (this.player_b.data.y - this.player_b.height / 2 - this.ball.height)) {
                            gameWin();
                            return;
                        }
                        this.ball.data.angle = 360 - this.ball.data.angle;
                    }
                }
            },
            object: {
                player_a: {
                    node: document.getElementById('player_a'),
                    height: document.getElementById('player_a').clientHeight,
                    data: {
                        y: 0,
                        speed: 10,
                        angle: 0,
                    },
                    update: function () {

                    }
                },
                player_b: {
                    node: document.getElementById('player_b'),
                    height: document.getElementById('player_b').clientHeight,
                    data: {
                        y: 0,
                        speed: 10,
                        angle: 0,
                    },
                    update: function () {
                        // player b move
                        if (global.object.ball.data.y - this.data.y > this.height / 3) {
                            this.data.angle = 0;
                        } else if (global.object.ball.data.y - this.data.y < -this.height / 3) {
                            this.data.angle = 180;
                        } else {
                            return;
                        }
                        var radian = this.data.angle * Math.PI / 180;
                        this.data.y += Math.cos(radian) * this.data.speed;
                    }
                },
                ball: {
                    node: document.getElementById('ball'),
                    height: document.getElementById('ball').clientHeight,
                    data: {
                        x: 100,
                        y: 0,
                        speed: 10,
                        angle: 60,
                        _speed: 0,
                    },
                    update: function () {
                        var radian = this.data.angle * Math.PI / 180;

                        // ball move
                        this.data.x += Math.sin(radian) * this.data._speed;
                        this.data.y += Math.cos(radian) * this.data._speed;
                    }
                },
            }
        }

        function handleMove(clientX, clientY) {
            if (clientX < global.half_width) {
                global.object.player_a.data.y = clientY;
                var transform_str = "translateY(" + String(global.object.player_a.data.y - global.object.player_a.height / 2) + "px)";
                global.object.player_a.node.style.transform = transform_str;
            }
        }

        function adapterMouse(e) {
            e.preventDefault();
            handleMove(e.clientX, e.clientY);
        }

        function adapterTouch(e) {
            e.preventDefault();
            handleMove(e.changedTouches[0].clientX, e.changedTouches[0].clientY);
            return;
        }

        function gameMain() {
            for (var i in global.object) {
                if (global.object[i].update) {
                    global.object[i].update();
                }
            }

            global.game.update.call(global.object);

            // ball show generate
            global.object.ball.node.style.top = global.object.ball.data.y + 'px';
            global.object.ball.node.style.left = global.object.ball.data.x + 'px';

            // player b genreate
            var transform_str = "translateY(" + String(global.object.player_b.data.y - global.object.player_b.height / 2) + "px)";
            global.object.player_b.node.style.transform = transform_str;
        }

        function addLisitener() {
            window.onmousemove = adapterMouse;
            window.addEventListener(
                'touchstart',
                adapterTouch,
                { passive: false }
            );
            window.addEventListener(
                'touchmove',
                adapterTouch,
                { passive: false }
            );
            window.addEventListener(
                'touchend',
                adapterTouch,
                { passive: false }
            );
        }
        function removeLisitener() {
            window.removeEventListener('mousemove', window);
            window.removeEventListener('touchstart', window);
            window.removeEventListener('touchmove', window);
            window.removeEventListener('touchend', window);
        }

        function gameStart() {
            removeLisitener();
            clearInterval(global.game.main);
            global.game.main = setInterval(gameMain, 20);
            for (var i in global.object) {
                for (var j in global.object[i].data) {
                    if (j.startsWith('_')) {
                        global.object[i].data[j] = global.object[i].data[j.substring(1)];
                    }
                }
            }
            document.getElementById('menu_btn_stop').innerText = "STOP";
            document.getElementById('menu_title').innerText = '';
            document.getElementById('menu_btn_stop').onclick = gameStop;
            addLisitener();
        }
        function gameStop() {
            clearInterval(global.game.main);
            global.game.main = null;
            removeLisitener();
            document.getElementById('menu_btn_stop').onclick = gameStart;
            document.getElementById('menu_btn_stop').innerText = "START";
        }
        function gameOver() {
            gameStop();
            window.addEventListener('touchstart', () => {
                if (global.game.main != null) {
                    return;
                };
                global.object.ball.data.angle = Math.random() * 90 + 30;
                global.object.ball.data.x = 0;
                global.object.ball.data.y = global.object.player_a.data.y;
                gameStart();
            });
            document.getElementById('menu_title').innerText = "GAME OVER";
        }
        function gameWin() {
            gameStop();
            window.addEventListener('touchstart', () => {
                if (global.game.main != null) {
                    return;
                }
                global.object.ball.data.angle = Math.random() * 90 + 30;
                global.object.ball.data.x = 0;
                global.object.ball.data.y = global.object.player_a.data.y;
                gameStart();
            });
            document.getElementById('menu_title').innerText = "YOU WIN";
        }
        function initGame() {
            document.getElementById('menu_btn_stop').onclick = gameStart;
            document.getElementById('menu_btn_stop').innerText = "START";
            global.object.ball.data.angle = Math.random() * 90 + 30;
            global.object.ball.data.y = global.object.player_a.data.y;
        }
        initGame();
    </script>
</body>

</html>